#include"MapDisplay.h" 

#include"Map.h"
#include"Unit.h"

#include<QGraphicsItemAnimation>
#include<QTimer>

#include<stdio.h>
#include<assert.h>

#define PI 3.14159265358979323846

MapDisplay::MapDisplay(Map *map):QGraphicsView(){
	m_map = map;
	m_pathItem = 0;
	m_distances = 0;
	m_scene = new QGraphicsScene(this);
	setScene(m_scene);
	
	m_fields = new QGraphicsEllipseItem**[NUM_ROWS];
	for(int i = 0; i < NUM_ROWS; i++){
		m_fields[i] = new QGraphicsEllipseItem*[NUM_COLS];
		for(int j = 0; j < NUM_COLS; j++){
			double x = j*40 + (i%2==1?20:0);
			double y = i*40;
			m_fields[i][j] = m_scene->addEllipse( QRectF(x, y, 40, 40), QPen(), brushForFieldType(m_map->field(i,j)->type()) );
			m_fields[i][j]->setZValue(-1.0);
			if(m_map->field(i,j)->occupiedBy()){
				QGraphicsTextItem *text = m_scene->addText(m_map->field(i,j)->occupiedBy()->tag() + "\n" + QString().setNum(m_map->field(i,j)->occupiedBy()->health()));
				text->setPos(x, y/*+10*/);
				m_textItemMap.insert(m_map->field(i,j)->occupiedBy(), text);
				text->setDefaultTextColor( m_map->field(i,j)->occupiedBy()->team() == TEAM_A ? Qt::red : Qt::blue );
			}
		}
	}
	connect(m_map, SIGNAL(unitDamaged(Unit*)), this, SLOT(slotUnitDamaged(Unit*)));
	connect(m_map, SIGNAL(turnEnded(Unit*)), this, SLOT(slotTurnEnded(Unit*)));
}

MapDisplay::~MapDisplay(){
	
}

QBrush MapDisplay::brushForFieldType(FieldType type){
	QBrush brush;
	switch(type){
		case FIELD_GRASS:
			brush = QBrush(Qt::white);
			break;
		case FIELD_ROCKS:
			brush = QBrush(Qt::darkGray);
			break;
		case FIELD_HILLS:
			brush = QBrush(Qt::lightGray);
			break;
		case FIELD_BUSH:
			brush = QBrush(Qt::green);
			break;
		case FIELD_FOREST:
			brush = QBrush(Qt::darkGreen);
			break;
		case FIELD_WATER:
			brush = QBrush(Qt::darkBlue);
			break;
		case FIELD_SWAMP:
			brush = QBrush(Qt::cyan);
			break;
	}
	return brush;
}

// enum FieldType{
// 	FIELD_GRASS,
// 	FIELD_ROCKS,
// 	FIELD_HILLS,
// 	FIELD_BUSH,
// 	FIELD_FOREST,
// 	FIELD_WATER,
// 	FIELD_SWAMP
// };

bool MapDisplay::doTurn(){
	bool ret = m_map->doTurn();
	bool changed = false;
	for( QMap<Unit*,QGraphicsTextItem*>::iterator it = m_textItemMap.begin(); it != m_textItemMap.end(); ++it ){
		int i = it.key()->field()->row();
		int j = it.key()->field()->col();
		double x = j*40 + (i%2==1?20:0);
		double y = i*40;
		if(it.value()->pos() != QPointF(x,y)){
			changed = true;
			if(m_pathItem==0){
				m_pathItem = new QGraphicsPathItem;
				m_scene->addItem(m_pathItem);
			}
			
			QPainterPath path(QPointF(it.value()->pos().x()+20, it.value()->pos().y()+20));
			it.value()->setPos(x,y);
			path.lineTo(QPointF(it.value()->pos().x()+20, it.value()->pos().y()+20));
			m_pathItem->setPath(path);
			m_pathItem->setZValue(1.0);
			
		}
	}
	
	if(!changed && m_pathItem){
		m_scene->removeItem(m_pathItem);
		delete m_pathItem;
		m_pathItem = 0;
	}
	
	return ret;
}

void MapDisplay::slotUnitDamaged(Unit *unit){
// 	QGraphicsEllipseItem *item = m_fields[unit->field()->row()][unit->field()->col()];
	
	QGraphicsTextItem *item = m_textItemMap[unit];
	if(unit->health() <= 0)
		m_textItemMap.remove(unit);
	item->setPlainText(unit->tag() + "\n" + QString().setNum(unit->health() >= 0 ? unit->health() : 0));
	QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
	animation->setItem(item);
	animation->setRotationAt(0,0);
	animation->setRotationAt(.25, /*PI/2.0*/90);
	animation->setRotationAt(.5, /*PI*/180);
	animation->setRotationAt(.75, /*3*PI/2.0*/270);
	animation->setRotationAt(1, /*2*PI*/360);
	animation->setStep(0.0);
	QTimer *timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
	
	m_animations.push_back(animation);
	m_timers.push_back(timer);
	m_counters.push_back(unit->health() > 0 ? 0 : -1);
	timer->start(100);
}

void MapDisplay::slotTurnEnded(Unit *unit){
	if(unit->health() <= 0){
		printf("MapDisplay::PANIC\n");
		return;
	}
	QGraphicsTextItem *item = m_textItemMap[unit];
	QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
	animation->setItem(item);
	animation->setTranslationAt(0, 0, 0);
	animation->setTranslationAt(.25, 0, 20.0);
	animation->setTranslationAt(.5, 0, 0);
	animation->setTranslationAt(.75, 0, -20.0);
	animation->setTranslationAt(1.0, 0, 0);
	animation->setStep(0.0);
	QTimer *timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
	
	m_animations.push_back(animation);
	m_timers.push_back(timer);
	m_counters.push_back(0);
	timer->start(100);
}

void MapDisplay::slotTimerTimeout(){
	QGraphicsItemAnimation *animation = m_animations.takeAt(0);
	QTimer *timer = m_timers.takeAt(0);
	int counter = m_counters.takeAt(0);
	
	if(counter==9 || counter == -10){
		animation->setStep(1.0);
		QGraphicsItem *item = animation->item();
		delete animation;
		timer->disconnect();
		delete timer;
		if(counter == -10){
			//TODO: Cleanup
			m_scene->removeItem(item);
			delete item;
		}
	}else{
		if(counter >= 0){
			counter++;
			animation->setStep(counter/10.0);
		}else{
			counter--;
			animation->setStep( -(counter+1)/10.0 );
		}
		m_animations.push_back(animation);
		m_timers.push_back(timer);
		m_counters.push_back(counter);
	}
}

void MapDisplay::showDistances(){
	assert(m_distances==0);
	Field *base = m_map->turnSequence()[0]->field();
	m_distances = new QGraphicsTextItem**[NUM_ROWS];
	for(int i = 0; i < NUM_ROWS; i++){
		m_distances[i] = new QGraphicsTextItem*[NUM_COLS];
		for(int j = 0; j < NUM_COLS; j++){
			double x = j*40 + (i%2==1?20:0) + 10;
			double y = i*40 + 10;
			m_distances[i][j] = m_scene->addText( QString().setNum(base->distance(m_map->field(i,j))) );
			m_distances[i][j]->setPos(QPointF(x,y));
		}
	}
}

void MapDisplay::hideDistances(){
	assert(m_distances!=0);
	for(int i = 0; i < NUM_ROWS; i++){
		for(int j = 0; j < NUM_COLS; j++){
			m_scene->removeItem(m_distances[i][j]);
			delete m_distances[i][j];
			m_distances[i][j] = 0;
		}
		delete [] m_distances[i];
		m_distances[i] = 0;
	}
	delete [] m_distances;
	m_distances = 0;
}